<?php

namespace MoChat\App\NewHome\Action;

use EasyWeChat\Work\Application;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\DbConnection\Db;
use MoChat\App\Corp\Utils\WeWorkFactory;
use MoChat\App\WorkDepartment\Contract\WorkDepartmentContract;
use MoChat\Framework\Action\AbstractAction;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use MoChat\App\Common\Middleware\DashboardAuthMiddleware;
use MoChat\App\Sales\Constants\SalesTaskStatusCode;
use MoChat\App\Sales\Contract\SalesClientTaskContract;
use MoChat\App\Sales\Contract\SalesClientTaskEmployeeContract;
use MoChat\App\Sales\Contract\SalesTaskContract;
use MoChat\Framework\Request\ValidateSceneTrait;
use MoChat\Framework\Exception\CommonException;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Plugin\Statistic\Logic\EmployeesLogic;

/**
 * 销售过程
 * @Controller
 */
class Sales extends AbstractAction
{
    use ValidateSceneTrait;

    /**
     * @Inject
     * @var StdoutLoggerInterface
     */
    protected $logger;

    /**
     * @Inject
     * @var EmployeesLogic
     */
    protected $employeesLogic;
    /**
     * @Inject
     * @var WorkDepartmentContract
     */
    protected $workDepartmentService;

    private function userOrder($data){
        $countFiled=$data['way']==2?Db::raw("COUNT(my_order.ID) as count"):Db::raw("COUNT(DISTINCT my_order.USER_ID) as count");
        if ($data['type'] > 2) {
            $userOrder = Db::connection('b2b')->table('user_order as order')
                ->join('order_status as status', function ($query) {
                    $query->on('status.ID', '=', 'order.ID')
                        ->where('status.PAYMENT', '=', 1);
                })
                ->join('user as user', 'user.id', '=', 'order.USER_ID')
                ->join('assign_customer_service as assign','assign.USER_ID','user.id')
                ->where('order.CREATE_TIME', '>=', $data['start_time'])
                ->where('order.CREATE_TIME', '<', $data['end_time'])
                ->select([
                    $countFiled,
                    Db::raw('DATE_FORMAT(my_order.CREATE_TIME,"%m-%d") as time')
                ])->groupBy([
                    'time'
                ])->get()->toArray();
        } else {
            $userOrder = Db::connection('b2b')->table('user_order as order')
                ->join('order_status as status', function ($query) {
                    $query->on('status.ID', '=', 'order.ID')
                        ->where('status.PAYMENT', '=', 1);
                })
                ->join('user as user', 'user.id', '=', 'order.USER_ID')
                ->join('assign_customer_service as assign','assign.USER_ID','user.id')
                ->where('order.CREATE_TIME', '>=', $data['start_time'])
                ->where('order.CREATE_TIME', '<', $data['end_time'])
                ->select([
                    $countFiled,
                    Db::raw('DATE_FORMAT(my_order.CREATE_TIME,"%H:00:00") as time')
                ])->groupBy([
                    'time',
                ])->get()->toArray();
        }
        return empty($userOrder) ? [] : array_column($userOrder, null, 'time');
    }

    private function clockRecord($data): array
    {
        $countFiled=$data['way']==2?Db::raw("COUNT(mc_record.id) as count"):Db::raw("COUNT(DISTINCT mc_record.client_id) as count");
        if ($data['type'] > 2) {
            $clockRecord = Db::table('clock_record as record')
                ->where('created_at', '>=', $data['start_time'])
                ->where('created_at', '<', $data['end_time'])
                ->select([
                    $countFiled,
                    Db::raw('DATE_FORMAT(mc_record.created_at,"%m-%d") as time')
                ])->groupBy(['time'])->get()->toArray();
        } else {
            $clockRecord = Db::table('clock_record as record')
                ->where('created_at', '>=', $data['start_time'])
                ->where('created_at', '<', $data['end_time'])
                ->select([
                    $countFiled,
                    Db::raw('DATE_FORMAT(mc_record.created_at,"%H:00:00") as time')
                ])->groupBy(['time'])->get()->toArray();
        }
        return empty($clockRecord) ? [] : array_column($clockRecord, null, 'time');

    }

    private function client($data): array
    {
        if ($data['type'] > 2) {
            $client = Db::table('client as client')
                ->where('created_at', '>=', $data['start_time'])
                ->where('created_at', '<', $data['end_time'])
                ->select([
                    Db::raw("COUNT(mc_client.id) as count"),
                    Db::raw('DATE_FORMAT(mc_client.created_at,"%m-%d") as time')
                ])->groupBy(['time'])->get()->toArray();
        } else {
            $client = Db::table('client as client')
                ->where('created_at', '>=', $data['start_time'])
                ->where('created_at', '<', $data['end_time'])
                ->select([
                    Db::raw("COUNT(mc_client.id) as count"),
                    Db::raw('DATE_FORMAT(mc_client.created_at,"%H:00:00") as time')
                ])->groupBy(['time'])->get()->toArray();
        }
        return empty($client) ? [] : array_column($client, null, 'time');
    }
    /**
     * 呼叫次数
     * @param $data
     * @return array
     */
    private function callRecord($data): array
    {
        $countFiled=$data['way']==2?Db::raw("COUNT(mc_record.id) as count"):Db::raw("COUNT(DISTINCT mc_record.client_id) as count");
        if ($data['type'] > 2) {
            $employeeCallOut = Db::table('call_record as record')
                ->where('call_type', 'out')
                ->where('created_time', '>=', $data['start_time'])
                ->where('created_time', '<', $data['end_time'])
                ->select([
                    $countFiled,
                    Db::raw('DATE_FORMAT(mc_record.created_time,"%m-%d") as time')
                ])->groupBy(['time'])->get()->toArray();
        } else {
            $employeeCallOut = Db::table('call_record as record')
                ->where('call_type', 'out')
                ->where('created_time', '>=', $data['start_time'])
                ->where('created_time', '<', $data['end_time'])
                ->select([
                    $countFiled,
                    Db::raw('DATE_FORMAT(mc_record.created_time,"%H:00:00") as time')
                ])->groupBy(['time'])->get()->toArray();
        }
        return empty($employeeCallOut) ? [] : array_column($employeeCallOut, null, 'time');
    }
    private function timeRange($data){
        $startTime=strtotime($data['start_time']);
        $endTime=strtotime($data['end_time']);
        $timeScope=[];
        if ($data['type']>2){
            while ($endTime>$startTime){
                $timeScope[]=date('m-d',$startTime);
                $startTime=$startTime+86400;
            }
        }else{
            while ($endTime>$startTime){
                $timeScope[]=date('H:00:00',$startTime);
                $startTime=$startTime+3600;
            }
        }
        return $timeScope;
    }
    /**
     * 根据微信企业ID获取easyWechat实例.
     *
     * @param int|string $corpId 微信corpid或企业表corpId
     */
    public function wxApp($corpId, string $type = 'user'): Application
    {
        $weWorkFactory = make(WeWorkFactory::class);
        if ($type === 'user') {
            return $weWorkFactory->getUserApp($corpId);
        }

        return $weWorkFactory->getContactApp($corpId);
    }
    private function wechatRecord($data,$user)
    {
        // 取出这个企业的所有成员
        $employeeList = $this->employeesLogic->getEmployees($user['corpIds'][0]);
        // 取出微信字母id
        $userIds = [];
        foreach ($employeeList as $item) {
            $userIds[] = $item['wxUserId'];
        }

        $result = [
            'chat_cnt' => 0,
        ];
        # #EasyWeChat获取「联系客户统计」数据
        $wx = $this->wxApp($user['corpIds'][0], 'contact')->external_contact_statistics;
        $start = 0;
        do {
            $wxUserId = array_slice($userIds, $start, 100);
            $start += 100;
            // 获取某些成员的某日期的统计数据
            $res = $wx->userBehavior($wxUserId, (string) strtotime($data['start_time']), (string) strtotime($data['end_time']));
            if ($res['errcode'] !== 0) {
                $this->logger->error(sprintf('获取「联系客户统计」数据 失败::[%s]', json_encode($res, JSON_THROW_ON_ERROR)));
            }
            $res = $res['behavior_data'];

            foreach ($res as $re) {
                $result['chat_cnt'] += @$re['chat_cnt'];
            }
        } while (count($wxUserId) === 100);
        return $result['chat_cnt'];
    }


    /**
     * @Middlewares({
     *     @Middleware(DashboardAuthMiddleware::class),
     * })
     * @RequestMapping(path="/dashboard/newHome/sales", methods="GET")
     */
    public function handle()
    {
        $user = user();
        // 判断用户绑定企业信息
        if (!isset($user['corpIds']) || count($user['corpIds']) !== 1) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '未选择登录企业，不可操作');
        }
        $data = $this->request->all();
        $this->validated($data);
        $data = $this->typeEnum($data);
        $client = $this->client($data);
        $employeeCallOut = $this->callRecord($data);//员工呼叫
        $clockRecord = $this->clockRecord($data);//打卡次数
        $orderUser = $this->userOrder($data);//企微沟通
        $timeScope=$this->timeRange($data);
        $employeeCallOutList=[];
        $clockRecordList=[];
        $orderUserList=[];
        $clientList=[];
        foreach ($timeScope as $item){
            $clientList[]=$client[$item]->count??0;
            $employeeCallOutList[]=$employeeCallOut[$item]->count??0;
            $clockRecordList[]=$clockRecord[$item]->count??0;
            $orderUserList[]=$orderUser[$item]->count??0;
        }

        $countFiled = $data['way'] == 2 ? Db::raw("COUNT(mc_record.id) as count") : Db::raw("COUNT(DISTINCT mc_record.client_id) as count");
        $employeeCallOutTotal = Db::table('call_record as record')
            ->where('call_type', 'out')
            ->where('created_time', '>=', $data['start_time'])
            ->where('created_time', '<', $data['end_time'])
            ->select([
                $countFiled,
            ])->first();
        $employeeCallOutTotal = empty($employeeCallOutTotal) ? 0 : $employeeCallOutTotal->count;


        $countFiled=$data['way']==2?Db::raw("COUNT(mc_record.id) as count"):Db::raw("COUNT(DISTINCT mc_record.client_id) as count");
        $clockRecordTotal = Db::table('clock_record as record')
            ->where('created_at', '>=', $data['start_time'])
            ->where('created_at', '<', $data['end_time'])
            ->select([
                $countFiled,
            ])->first();
        $clockRecordTotal=empty($clockRecordTotal)?0:$clockRecordTotal->count;

        $clientTotal = Db::table('client as client')
            ->select([
                Db::raw("COUNT(mc_client.id) as count"),
            ])->first();
        $clientTotal=empty($clientTotal)?0:$clientTotal->count;

        $countFiled=$data['way']==2?Db::raw("COUNT(my_order.ID) as count"):Db::raw("COUNT(DISTINCT my_order.USER_ID) as count");
        $userOrderTotal = Db::connection('b2b')->table('user_order as order')
            ->join('order_status as status', function ($query) {
                $query->on('status.ID', '=', 'order.ID')
                    ->where('status.STATUS_', '>=', 0);
            })
            ->join('user as user', 'user.id', '=', 'order.USER_ID')
//            ->leftJoin('assign_customer_service as assign','assign.USER_ID','user.id')
            ->where('order.CREATE_TIME', '>=', $data['start_time'])
            ->where('order.CREATE_TIME', '<', $data['end_time'])
            ->select([
                $countFiled,
            ])->first();
        $userOrderTotal=empty($userOrderTotal)?0:$userOrderTotal->count;

        return [
            'total' => [
                [
                    'title' => '客户总数',
                    'number' =>  $clientTotal,
                ],
                [
                    'title' => '呼出客户数',
                    'number' => $employeeCallOutTotal,
                ],
                [
                    'title' => '外勤打卡客户数',
                    'number' => $clockRecordTotal,
                ],
                [
                    'title' => '企微沟通客户数',
                    'number' => $this->wechatRecord($data,$user),
                ],
                [
                    'title' => $data['way']==2?'下单订单数':'下单客户数',
                    'number' => $userOrderTotal,
                ]
            ],
            'x' => $timeScope,
            'client' => $clientList,
            'callOut' => $employeeCallOutList,
            'clock' => $clockRecordList,
            'wechat' => 0,
            'orderUser' => $orderUserList,
        ];
    }

    private function typeEnum($data)
    {
        //默认
        $start = date('Y-m-d 00:00:00');
        $timeRange = [
            'start_time' => $start,
            'end_time' => date('Y-m-d H:i:s', strtotime($start) + 86400),
        ];
        //今日
        if ($data['type'] == 1) {
            $timeRange = [
                'start_time' => $start,
                'end_time' => date('Y-m-d H:i:s', strtotime($start) + 86400),
            ];
        }
        //昨日
        if ($data['type'] == 2) {
            $timeRange = [
                'start_time' => date('Y-m-d 00:00:00', strtotime('-1 day')),
                'end_time' => date('Y-m-d 00:00:00'),
            ];
        }
        //本月
        if ($data['type'] == 3) {
            $timeRange = [
                'start_time' => date('Y-m-01 00:00:00'),
                'end_time' => date('Y-m-d H:i:s'),
            ];
        }
        //上月
        if ($data['type'] == 4) {
            $start = date('Y-m-01 00:00:00', strtotime('-1 month'));
            $timeRange = [
                'start_time' => date('Y-m-01 00:00:00', strtotime('-1 month')),
                'end_time' => date('Y-m-d H:i:s', strtotime('+1 month', strtotime($start))),
            ];
        }
        //本周
        if ($data['type'] == 5) {
            $week = date('w');
            $day = $week ? $week - 1 : 6;
            $timeRange = [
                'start_time' => date('Y-m-d 00:00:00', strtotime('-' . $day . ' day')),
                'end_time' => date('Y-m-d H:i:s'),
            ];
        }
        //默认
        return array_merge($data, $timeRange);
    }


    /**
     * 验证规则.
     */
    protected function rules(): array
    {
        return [
            'type' => 'in:1,2,3,4',
            'way' => 'in:1,2'
        ];
    }

    /**
     * 获取已定义验证规则的错误消息.
     */
    protected function messages(): array
    {
        return [
            'type.in' => 'type参数错误',
            'way.in' => 'way参数错误',
        ];
    }

}
